#pragma once
#ifndef CONJUGRADIENT_H
#define CONJUGRADIENT_H

#include "stdafx.h"
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <fstream>
#include "optimization.h"
#include <vector>
#include "OptData.h"
#include "Constraint.h"
#include "time.h"

using namespace std;
using namespace alglib;

class ConjuGradientOpt
{
public:
	static ConjuGradientOpt* Instance();
	//void optimization(vector<double> *resutlWeight,OptData* optData, vector<SConstraint> *pConstrain);
	//the original optimization algorithm, which the objective function is (DijWij^2-Dp)^2
	void optimization(vector<double> *resutlWeight,OptData* optData, vector<SConstraint> *pConstrain, vector<double> *objFunValue,int maxIter=0);

	//modified objective function, it is still (DijWij^2-Dp)^2
	//at the beginning of the algorithm, program will check weights of beamlets to guarantee the initial value of weights used in algorithm is not equal to 0   
	void optimization_modify_1(vector<double> *resutlWeight,OptData* optData, vector<SConstraint> *pConstrain, vector<double> *objFunValue,int maxIter=0);


private:
	ConjuGradientOpt(void){};
	ConjuGradientOpt(const ConjuGradientOpt&);

	static void function_grad(const real_1d_array &x, double &func, real_1d_array &grad, void *ptr);
	static void function_grad_modify_1(const real_1d_array &x, double &func, real_1d_array &grad, void *ptr);
	//static vector<double> *g_pDose;

	static OptData *g_optData;
	static vector<SConstraint> *g_pConstraints;
	static vector<double> *g_objFunValue;
};

#endif

